<!DOCTYPE html>
<html>

<head>
	<meta charset="utf-8">
	<title>VSCode Tests</title>
	<link href="../../../node_modules/mocha/mocha.css" rel="stylesheet" />
</head>

<body>
	<div id="mocha"></div>
	<script src="../../../node_modules/mocha/mocha.js"></script>

	<script>

		// !!! DO NOT CHANGE !!!
		// Our unit tests may run in environments without
		// display (e.g. from builds) and tests may by
		// accident bring up native dialogs or even open
		// windows. This we cannot allow as it may crash
		// the test run.
		// !!! DO NOT CHANGE !!!
		window.open = function () { throw new Error('window.open() is not supported in tests!'); };
		window.alert = function () { throw new Error('window.alert() is not supported in tests!'); }
		window.confirm = function () { throw new Error('window.confirm() is not supported in tests!'); }

		// Ignore uncaught cancelled promise errors
		window.addEventListener('unhandledrejection', e => {
			const name = e && e.reason && e.reason.name;

			if (name === 'Canceled') {
				e.preventDefault();
				e.stopPropagation();
			}
		});
	</script>
	<script>
		const urlParams = new URLSearchParams(window.location.search);
		const argv = JSON.parse(urlParams.get('argv'));

		const outdir = argv.build ? 'out-build' : 'out';
		const basePath = require('path').join(__dirname, `../../../${outdir}/`);
		const baseUrl = require('url').pathToFileURL(basePath);

		// Tests run in a renderer that IS node-enabled. So we will encounter imports for node-modules which isn't
		// supported by blink/chromium. To work around this, we generate an import map that maps all node modules
		// to a blob that exports all properties of the module as named exports and the module itself as default.

		function asRequireBlobUri(name) {
			let _mod;
			try {
				_mod = require(name);

			} catch (err) {
				// These are somewhat expected because of platform differences (windows vs mac vs linux) or because of node/electron binary differences
				// console.error(`[ESM] Failed to require ${name}`);
				// console.error(err);
				return undefined;
			}

			// export all properties and the module itself as default
			let jsSrc = `const _mod = require('${name}')\n`;
			for (const name of Object.keys(_mod)) {
				jsSrc += `export const ${name} = _mod['${name}'];\n`;
			}
			jsSrc += `export default _mod;\n`;

			const blob = new Blob([jsSrc], { type: 'application/javascript' });
			const url = URL.createObjectURL(blob);
			return url;
		}

		// generate import map
		const importMap = {
			imports: {
				assert: new URL('../test/unit/assert.js', baseUrl).href,
				sinon: new URL('../node_modules/sinon/pkg/sinon-esm.js', baseUrl).href,
				'sinon-test': new URL('../node_modules/sinon-test/dist/sinon-test-es.js', baseUrl).href,
				'electron': asRequireBlobUri('electron'),
			}
		};

		const builtin = require('module').builtinModules.filter(mod => !mod.startsWith('_') && !mod.startsWith('electron/js2c/')).sort();
		const dependencies = Object.keys(require('../../../package.json').dependencies).sort();
		const optionalDependencies = Object.keys(require('../../../package.json').optionalDependencies).sort();
		const dependenciesRemote = Object.keys(require('../../../remote/package.json').dependencies).sort();

		for (const name of new Set([].concat(builtin, dependencies, optionalDependencies, dependenciesRemote))) {
			const url = asRequireBlobUri(name);
			if (!url) {
				continue;
			}

			importMap.imports[name] = url;
		}

		//2: CSS modules
		const style = document.createElement('style');
		style.type = 'text/css';
		document.head.appendChild(style);

		globalThis._VSCODE_CSS_LOAD = function (url) {
			style.sheet.insertRule(`@import url(${url});`);
		};

		const { promisify } = require('util');
		globalThis._VSCODE_TEST_INIT = promisify(require('glob'))('**/*.css', { cwd: basePath }).then(cssModules => {
			for (const cssModule of cssModules) {
				const cssUrl = new URL(cssModule, baseUrl).href;
				const jsSrc = `globalThis._VSCODE_CSS_LOAD('${cssUrl}');\n`;
				const blob = new Blob([jsSrc], { type: 'application/javascript' });
				importMap.imports[cssUrl] = URL.createObjectURL(blob);
			}

		}).then(() => {
			const rawImportMap = JSON.stringify(importMap, undefined, 2);
			const importMapScript = document.createElement('script');
			importMapScript.type = 'importmap';
			importMapScript.textContent = rawImportMap;
			document.head.append(importMapScript);
		});
	</script>
	<script src="./renderer.js"></script>
</body>

</html>
